/* 
 * irtree.hpp
 * 
 */

#ifndef IRTREE_HPP
#define	IRTREE_HPP

#define BINOP_PLUS       51
#define BINOP_SUB        52
#define BINOP_MULT       54
#define BINOP_DIV        53
#define BINOP_ANDLOGIC   57
#define BINOP_ORLOGIC    59
#define CJUMP_EQUAL      45
#define CJUMP_NOTEQUAL   50
#define CJUMP_LESST      46
#define CJUMP_GREATERT   48
#define CJUMP_LESSEQ     47
#define CJUMP_GREATEREQ  49
#define BINOP_ORBIT      58
#define BINOP_ANDBIT     56
#define BINOP_MOD        55

class VisitorIRT;
class VisitorIRTCanonizer;
class VisitorIRTPrint;

class StmtFragment {
public:
    virtual int acceptVisitor(VisitorIRT *v) = 0;
    virtual StmtFragment* acceptVisitor(VisitorIRTCanonizer *v) = 0;

};

class Local_Access{
public:
    virtual StmtFragment* access_code() = 0;
};

class Frame{
public:
    virtual void addLocal(bool, int, char*, int) = 0;
    virtual void addParam(bool, int, char*, int) = 0;
    virtual int acceptVisitor(VisitorIRT *v) = 0;
    virtual void acceptVisitor(VisitorIRTCanonizer *v) = 0;

};

class Fragment {
public:
    virtual int acceptVisitor(VisitorIRT *v) = 0;
    virtual void acceptVisitor(VisitorIRTCanonizer *v) = 0;

};

/**
 * Abstract Class IRNStm
 */
class IRNStm : public StmtFragment{
public:
    virtual int acceptVisitor(VisitorIRT *v) = 0;
    virtual IRNStm* acceptVisitor(VisitorIRTCanonizer *v) = 0;

};

/**
 * Abstract Class IRNExp
 */
class IRNExp : public StmtFragment{
public:
    virtual int acceptVisitor(VisitorIRT *v) = 0;
    virtual IRNExp* acceptVisitor(VisitorIRTCanonizer *v) = 0;

};

class StmtFragmentList{
public:
    StmtFragment *stmFrag;
    StmtFragmentList *nextStmFrag;
public:
    StmtFragmentList(StmtFragment *stmFrag, StmtFragmentList *nextStmFrag);
    ~StmtFragmentList();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Access_List{
public:
    Access_List *next;
    Local_Access *access;
public:
    Access_List(Local_Access *access, Access_List *next);
    ~Access_List();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Label{
public:
    char* Label_Name;
public:
    Label();
    Label(char* name);
    ~Label();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Temp{
public:
    char* name;
public:
    Temp();
    Temp(char* name);
    ~Temp();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Label_List{
public:
    Label *label;
    Label_List *next;
public:
    Label_List(Label *name, Label_List *next);
    ~Label_List();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Temp_List{
public:
    Temp *temp;
    Temp_List *next;
public:
    Temp_List(Temp* temp, Temp_List *next);
    ~Temp_List();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class FragmentList {
public:
    Fragment *frag;
    FragmentList *nextFrag;
public:
    FragmentList(Fragment *frag, FragmentList *nextFrag);
    ~FragmentList();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Method : public Fragment {
public:
    StmtFragmentList *body;
    Frame *frame;
public:
    Method(Frame *f, StmtFragmentList *body);
    ~Method();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class Literal_Frag : public Fragment {
public:
    Label *label_literal;
public:
    Literal_Frag(char *literal);
    ~Literal_Frag();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class InFrame : public Local_Access {
public:
    int offset;
    int type;
    bool isParam;
    char* name;
public:
    InFrame(int offset, int type, bool isParam, char* name);
    ~InFrame();
    StmtFragment* access_code();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};


class InReg : public Local_Access {
public:
    Temp *temp;
    int type;
    bool isParam;
    char* name;
public:
    InReg(Temp *temp, int type, bool isParam, char* name);
    ~InReg();
    StmtFragment* access_code();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class FrameMIPS : public Frame {
public:
    int offSetAmount;
    int offSetParamAmount;
    int number_of_params;
    int param_size;
    Temp *returnReg;
    Label *label;
    Label *returnAddress;
    Access_List *access_list;
    Temp_List *tempList;
public:
    FrameMIPS();
    ~FrameMIPS();
    void addParam(bool escape, int tambytes, char* paramName, int type);
    void addLocal(bool escape, int tambytes, char* varName, int type);
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};


class IRNStmList{
public:
    IRNStm *stm;
    IRNStmList *tail;
public:
    IRNStmList(IRNStm*, IRNStmList*);
    ~IRNStmList();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class IRNExpList{
public:
    IRNExp *head;
    IRNExpList *tail;
public:
    IRNExpList(IRNExp*, IRNExpList*);
    ~IRNExpList();
    int acceptVisitor(VisitorIRT *v);
    void acceptVisitor(VisitorIRTCanonizer *v);
    
};

class IRNConst : public IRNExp{
public:
    int value;
public:
    IRNConst(int);
    ~IRNConst();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNConstf : public IRNExp{
public:
    double value;
public:
    IRNConstf(double);
    ~IRNConstf();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNName : public IRNExp{
public:
    Label *label;
public:
    IRNName(Label*);
    ~IRNName();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNTemp : public IRNExp{
public:
    Temp *temp;
public:
    IRNTemp(Temp*);
    ~IRNTemp();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNBinop : IRNExp{
public:
    int binop;
    IRNExp *left;
    IRNExp *right;
public:
    IRNBinop(int, IRNExp*, IRNExp*);
    ~IRNBinop();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNMem : IRNExp{
public:
    IRNExp *exp;
public:
    IRNMem(IRNExp*);
    ~IRNMem();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNCall : IRNExp{
public:
    IRNExp *func;
    IRNExpList *args;
public:
    IRNCall(IRNExp*, IRNExpList*);
    ~IRNCall();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNEseq : IRNExp{
public:
    IRNStm *stm;
    IRNExp *exp;
public:
    IRNEseq(IRNStm*,IRNExp*);
    ~IRNEseq();
    int acceptVisitor(VisitorIRT *v);
    IRNExp* acceptVisitor(VisitorIRTCanonizer* v);
};

class IRNMove : public IRNStm{
public:
    IRNExp *destination;
    IRNExp *source;
public:
    IRNMove(IRNExp*, IRNExp*);
    ~IRNMove();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNExpStm : IRNStm{
public:
    IRNExp *exp;
public:
    IRNExpStm(IRNExp*);
    ~IRNExpStm();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNJump : IRNStm{
public:
    IRNExp *exp;
public:
    IRNJump(IRNExp*);
    ~IRNJump();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNCJump : IRNStm{
public:
    int relOp;
    IRNExp *left;
    IRNExp *right;
    Label *iftrue;
    Label *iffalse;
public:
    IRNCJump(int, IRNExp*, IRNExp*, Label*, Label*);
    ~IRNCJump();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNSeq : public IRNStm{
public:
    IRNStm *left;
    IRNStm *right;
public:
    IRNSeq(IRNStm*, IRNStm*);
    ~IRNSeq();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer* v);
    
};

class IRNLabel : public IRNStm{
public:
    Label *label;
public:
    IRNLabel(Label*);
    ~IRNLabel();
    int acceptVisitor(VisitorIRT *v);
    IRNStm* acceptVisitor(VisitorIRTCanonizer *v);
    
};

#endif	/* IRTREE_HPP */